package com.mz;

import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by germmy on 17/9/27.
 * 1、改用流
 * 2、读文件加上UTF8
 * 3、传到oschina上
 * 4、打成jar包出来
 * 5、超时时间未设置
 * 6、休眠时间未设置
 * 7、遇到一个有异常，不应该全部停止
 * 8、List结果集区分用Lambda实现，妈的想了一下午思绪超级凌乱
 */
public class MyClient {


    public static final int TIME_OUT = 10;
    public static final String HTTP_CODE_404 = "404";
    public static final String HTTP_CODE_403 = "403";//运维禁止
    public static final String HTTP_CODE_200 = "200";
    public static final String HTTP_CODE_405 = "405";
    public static final String HTTP_CODE_500 = "500";
    public static final String HTTP_CODE_UNKNOWN = "unknown";
    public static final String HTTP_CODE_TIMEOUT = "timeout";


    public static  int expectedTotal;
    public static  int expected403Total;

    //config
//    public  static  String configFilePath="/Java_Files/config/";
    private static String urlFileName = "urls.txt";
    private static String configfileName = "config.properties";
    private static String expectedTotalKey = "url.total";
    private static String expected403TotalKey = "url.403.total";




    public static void main(String args[]) {

        MyClient myClient = new MyClient();

        init();

        //0.开始
        System.out.println("注意：");
        System.out.println("1、不能有空行，否则空行后面的将被忽略...");
        System.out.println("2、不能有非http行，否则无法解析...");
        System.out.println("解析url开始...");

        //200 list
        List<InvokeResultEntity> list200 = new ArrayList<InvokeResultEntity>();

        //404 list
        List<InvokeResultEntity> list404 = new ArrayList<InvokeResultEntity>();

        //405 list
        List<InvokeResultEntity> list405 = new ArrayList<InvokeResultEntity>();

        //timeout
        List<InvokeResultEntity> listTimeout = new ArrayList<InvokeResultEntity>();

        //unknown
        List<InvokeResultEntity> listUnknown = new ArrayList<InvokeResultEntity>();

        //500
        List<InvokeResultEntity> list500 = new ArrayList<InvokeResultEntity>();

        //500
        List<InvokeResultEntity> list403 = new ArrayList<InvokeResultEntity>();

        try {
            List<InvokeResultEntity> invokeResultEntityList = myClient.run();
            if (null != invokeResultEntityList && invokeResultEntityList.size() > 0) {
                //结果集划分
                for (InvokeResultEntity invokeResultEntity : invokeResultEntityList) {
                    if (invokeResultEntity.getHttpCode().equals(MyClient.HTTP_CODE_200)) {
                        list200.add(invokeResultEntity);

                    } else if (invokeResultEntity.getHttpCode().equals(MyClient.HTTP_CODE_404)) {
                        list404.add(invokeResultEntity);

                    } else if (invokeResultEntity.getHttpCode().equals(MyClient.HTTP_CODE_405)) {
                        list405.add(invokeResultEntity);

                    } else if (invokeResultEntity.getHttpCode().equals(MyClient.HTTP_CODE_TIMEOUT)) {
                        listTimeout.add(invokeResultEntity);

                    } else if (invokeResultEntity.getHttpCode().equals(MyClient.HTTP_CODE_UNKNOWN)) {
                        listUnknown.add(invokeResultEntity);

                    } else if (invokeResultEntity.getHttpCode().equals(MyClient.HTTP_CODE_500)) {
                        list500.add(invokeResultEntity);

                    } else if (invokeResultEntity.getHttpCode().equals(MyClient.HTTP_CODE_403)) {
                        list403.add(invokeResultEntity);
                    }
                }

                //分别打印
                int actualSum = list200.size() + list404.size() + list405.size() + list500.size() + listTimeout.size() + listUnknown.size() + list403.size();
//                System.out.println(actualSum + "个的结果汇总如下:");
                if (null != list200 && list200.size() > 0) {
                    System.out.println(list200.size() + "个200的接口如下:");
                    for (InvokeResultEntity invokeResultEntity : list200) {
                        System.out.println(invokeResultEntity.getUrl() + "----" + invokeResultEntity.getHttpCode());
                    }
                } else {
                    System.out.println("无200接口");
                }

                System.out.println("----分割符-----------------------------------------------------");


                if (null != list404 && list404.size() > 0) {
                    System.out.println(list404.size() + "个404的接口如下:");
                    for (InvokeResultEntity invokeResultEntity : list404) {
                        System.out.println(invokeResultEntity.getUrl() + "----" + invokeResultEntity.getHttpCode());
                    }
                } else {
                    System.out.println("无404接口");
                }

                System.out.println("----分割符-----------------------------------------------------");


                if (null != list404 && list405.size() > 0) {
                    System.out.println(list405.size() + "个405的接口如下:");
                    for (InvokeResultEntity invokeResultEntity : list405) {
                        System.out.println(invokeResultEntity.getUrl() + "----" + invokeResultEntity.getHttpCode());
                    }
                } else {
                    System.out.println("无405接口");
                }

                System.out.println("----分割符-----------------------------------------------------");


                if (null != listTimeout && listTimeout.size() > 0) {
                    System.out.println(listTimeout.size() + "个timeout的接口如下:");
                    for (InvokeResultEntity invokeResultEntity : listTimeout) {
                        System.out.println(invokeResultEntity.getUrl() + "----" + invokeResultEntity.getHttpCode());
                    }
                } else {
                    System.out.println("无超时接口");
                }

                System.out.println("----分割符-----------------------------------------------------");


                if (null != list500 && list500.size() > 0) {
                    System.out.println(list500.size() + "个500的接口如下:");
                    for (InvokeResultEntity invokeResultEntity : list500) {
                        System.out.println(invokeResultEntity.getUrl() + "----" + invokeResultEntity.getHttpCode());
                    }
                } else {
                    System.out.println("无500接口");
                }

                System.out.println("----分割符-----------------------------------------------------");

                if (null != listUnknown && listUnknown.size() > 0) {
                    System.out.println(listUnknown.size() + "个unknown的接口如下:");
                    for (InvokeResultEntity invokeResultEntity : listUnknown) {
                        System.out.println(invokeResultEntity.getUrl() + "----" + invokeResultEntity.getHttpCode());
                    }
                } else {
                    System.out.println("无unknown接口");
                }

                System.out.println("----分割符-----------------------------------------------------");

                if (null != list403 && list403.size() > 0) {
                    System.out.println(list403.size() + "个403的接口如下:");
                    for (InvokeResultEntity invokeResultEntity : list403) {
                        System.out.println(invokeResultEntity.getUrl() + "----" + invokeResultEntity.getHttpCode());
                    }
                } else {
                    System.out.println("无403接口");
                }
                //在有403的情况下，判断下403是否相等
                if(list403.size()>0){
                    if(list403.size() == expectedTotal){
                        System.out.println("【期待的403总数是:"+expectedTotal+",实际的403总数是:"+list403.size()+"】,2者相等,【OK】");
                    }else{
                        System.err.println("【期待的403总数是:"+expectedTotal+",实际的403总数是:"+list403.size()+"】,2者不相等,【ERROR】");
                    }
                }else{
                    //判断下总值是否相等
                    if(actualSum == expectedTotal){
                        System.out.println("【期待的总数是:"+expectedTotal+",实际的总数是:"+actualSum+"】,2者相等,【OK】");
                    }else{
                        System.err.println("【期待的总数是:"+expectedTotal+",实际的总数是:"+actualSum+"】,2者不相等,【ERROR】");
                    }
                }
            } else {
                System.err.println("总结果集为空");
            }

            System.out.println("解析url结束...");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    public void test() throws Exception {
        String line;
        List<String> result=new ArrayList<String>();
        StringBuilder stringBuilder=new StringBuilder();
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String url = "http://www.nonobank.com/Account/degreeCard";
//        String url = "http://www.nonobank.com/MicroSiteApi/UploadPhoneBook";
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response1 = httpclient.execute(httpGet);
        try {
            System.out.println("返回状态为:" + response1.getStatusLine());
            InputStream inputStream=response1.getEntity().getContent();
            InputStreamReader reader = new InputStreamReader(
                    inputStream); // 建立一个输入流对象reader
            BufferedReader br = new BufferedReader(reader); // 建立一个对象，它把文件内容转成计算机能读懂的语言
            while ((line = br.readLine()) != null) {
                stringBuilder.append(line);
            }

            System.out.println("result:"+stringBuilder.toString());


            if(stringBuilder.toString().indexOf("升级维护(403)")>0){
                System.out.println("维护中");
            }else{
                System.out.println("网页正常");
            }


            if (response1.getStatusLine().toString().indexOf("200 OK") > 0) {
                System.out.println(url + "----连接成功");
            } else {
                if (response1.getStatusLine().toString().indexOf("404 Not Found") > 0) {
                    System.out.println(url + "----404");
                } else {
                    System.out.println(url + "----连接失败");
                }
            }
            HttpEntity entity1 = response1.getEntity();
            EntityUtils.consume(entity1);
        } finally {
            response1.close();
        }
    }


    public List<InvokeResultEntity> run() throws Exception {
//        String filePath="/Java_Files/config/";
        //1.从文件中读取出所有url
//        List<String> rawList = readFile(configFilePath+urlFileName);
        List<String> rawList = readFile(urlFileName);
        //1.1 将文件中的中文剔除掉
        List<String> urlList = filterList(rawList);
        //2.调用url解析结果
        List<InvokeResultEntity> invokeResultEntityList = new ArrayList<InvokeResultEntity>();
        for (String url : urlList) {
            try {
                InvokeResultEntity invokeResultEntity = invokeUrl(url);
                if (invokeResultEntity.getHttpCode().equals(HTTP_CODE_200)
                        || invokeResultEntity.getHttpCode().equals(HTTP_CODE_404)
                        || invokeResultEntity.getHttpCode().equals(HTTP_CODE_405)
                        || invokeResultEntity.getHttpCode().equals(HTTP_CODE_UNKNOWN)
                        || invokeResultEntity.getHttpCode().equals(HTTP_CODE_500)
                        || invokeResultEntity.getHttpCode().equals(HTTP_CODE_403)) {
                    invokeResultEntityList.add(invokeResultEntity);
                }
            } catch (SocketTimeoutException ste) {
//                System.out.println(url + "----连接超时");
                InvokeResultEntity invokeResultEntityTemp = new InvokeResultEntity();
                invokeResultEntityTemp.setSuccess(false);
                invokeResultEntityTemp.setUrl(url);
                invokeResultEntityTemp.setHttpCode(HTTP_CODE_TIMEOUT);
                invokeResultEntityList.add(invokeResultEntityTemp);
            } catch (HttpHostConnectException hce) {
//                System.out.println(url + "----连接超时");
                InvokeResultEntity invokeResultEntityTemp = new InvokeResultEntity();
                invokeResultEntityTemp.setSuccess(false);
                invokeResultEntityTemp.setUrl(url);
                invokeResultEntityTemp.setHttpCode(HTTP_CODE_TIMEOUT);
                invokeResultEntityList.add(invokeResultEntityTemp);
            }
            Thread.sleep(200);
        }

        return invokeResultEntityList;
    }


    public void invokeUrlSingle(String url) throws Exception {
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(TIME_OUT * 1000)
                .setConnectionRequestTimeout(TIME_OUT * 1000)
                .setSocketTimeout(TIME_OUT * 1000).build();
//        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpClient httpclient =
                HttpClientBuilder.create().setDefaultRequestConfig(config).build();
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response1 = httpclient.execute(httpGet);

        try {
            System.out.println("返回状态为:" + response1.getStatusLine());
            if (response1.getStatusLine().toString().indexOf("200 OK") > 0) {
                System.out.println(url + "----200，连接成功");
            } else {
                if (response1.getStatusLine().toString().indexOf("404 Not Found") > 0) {
                    System.out.println(url + "----404，连接失败");
                } else if (response1.getStatusLine().toString().indexOf("405 Method Not Allowed") > 0) {
                    System.out.println(url + "----405，连接失败");
                } else if (response1.getStatusLine().toString().indexOf("500 Internal Server Error") > 0) {
                    System.out.println(url + "----500，连接失败");
                } else {
                    System.out.println(url + "----未知状态，连接失败");
                }
            }
            HttpEntity entity1 = response1.getEntity();
            EntityUtils.consume(entity1);
        } finally {
            response1.close();
        }

    }


    private InvokeResultEntity invokeUrl(String url) throws Exception {
        InvokeResultEntity invokeResultEntity = new InvokeResultEntity();
        invokeResultEntity.setUrl(url);
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(TIME_OUT * 1000)
                .setConnectionRequestTimeout(TIME_OUT * 1000)
                .setSocketTimeout(TIME_OUT * 1000).build();
        CloseableHttpClient httpclient =
                HttpClientBuilder.create().setDefaultRequestConfig(config).build();
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response1 = httpclient.execute(httpGet);
        try {
//            System.out.println("返回状态为:" + response1.getStatusLine());
            invokeResultEntity.setHttpCompleteStatus(response1.getStatusLine().toString());
            if (response1.getStatusLine().toString().indexOf("200 OK") > 0) {
                if(isContains403(response1)){
                    System.out.println(url + "----403-B,运维禁止成功");
                    invokeResultEntity.setHttpCode(HTTP_CODE_403);
                }else{
                    System.out.println(url + "----200,连接成功");
                    invokeResultEntity.setHttpCode(HTTP_CODE_200);
                }
                invokeResultEntity.setSuccess(true);
            } else if (response1.getStatusLine().toString().indexOf("403") > 0) {//add 403
                System.out.println(url + "----403,连接失败");
                invokeResultEntity.setSuccess(false);
                invokeResultEntity.setHttpCode(HTTP_CODE_403);
            }else if (response1.getStatusLine().toString().indexOf("405 Method Not Allowed") > 0) {
                System.out.println(url + "----405,连接失败");
                invokeResultEntity.setSuccess(false);
                invokeResultEntity.setHttpCode(HTTP_CODE_405);
            } else if (response1.getStatusLine().toString().indexOf("404 Not Found") > 0) {
                System.out.println(url + "----404，连接失败");
                invokeResultEntity.setSuccess(false);
                invokeResultEntity.setHttpCode(HTTP_CODE_404);
            } else if (response1.getStatusLine().toString().indexOf("500 Internal Server Error") > 0) {
                System.out.println(url + "----500，连接失败");
                invokeResultEntity.setSuccess(false);
                invokeResultEntity.setHttpCode(HTTP_CODE_500);
            } else {
                System.out.println(url + "----连接失败");
                invokeResultEntity.setSuccess(false);
                invokeResultEntity.setHttpCode(HTTP_CODE_UNKNOWN);
            }
            HttpEntity entity1 = response1.getEntity();
            EntityUtils.consume(entity1);
        } finally {
            response1.close();
        }
        return invokeResultEntity;
    }


    /**
     * 多取文件，直接用流读取
     * 注意：此程序读到空行即中止
     *
     * @return
     * @throws Exception
     */
    public List<String> readFileForClasspath(String fileName) throws Exception {
        String line;
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileName);
        List<String> result = new ArrayList<String>();
        InputStreamReader reader = new InputStreamReader(
                inputStream); // 建立一个输入流对象reader
        BufferedReader br = new BufferedReader(reader); // 建立一个对象，它把文件内容转成计算机能读懂的语言
        String tempLine=br.readLine();
        line=tempLine.trim();
        while (line != null && !line.equals("")) {
//            System.out.println("line is :"+line);
            result.add(line);
            tempLine=br.readLine();
            if(tempLine!=null && !tempLine.equals("")){
                line =tempLine.trim();
            }else{
                line=null;
            }
        }
        return result;
    }

    /**
     * 多取文件，直接用流读取
     * 注意：此程序读到空行即中止
     *
     * @return
     * @throws Exception
     */
    public List<String> readFile(String fileName) throws Exception {
        String line;
//        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(urlFileName);
        InputStream inputStream=new FileInputStream(new File(fileName));
        List<String> result = new ArrayList<String>();
        InputStreamReader reader = new InputStreamReader(
                inputStream); // 建立一个输入流对象reader
        BufferedReader br = new BufferedReader(reader); // 建立一个对象，它把文件内容转成计算机能读懂的语言
        String tempLine=br.readLine();
        line=tempLine.trim();
        while (line != null && !line.equals("")) {
//            System.out.println("line is :"+line);
            result.add(line);
            tempLine=br.readLine();
            if(tempLine!=null && !tempLine.equals("")){
                line =tempLine.trim();
            }else{
                line=null;
            }
        }
        return result;
    }






    /**
     * 传入一个原生List,将中文剔除掉
     *
     * @param rawList
     * @return
     */
    private List<String> filterList(List<String> rawList) {
        List<String> newList = new ArrayList<String>();
        for (String str : rawList) {
//            if(str==null || str==""){
//                throw new RuntimeException("不允许有空行");
//            }
            if (str.indexOf(" ") > 0) {
                String newStr = str.substring(0, str.indexOf(" "));
                newList.add(newStr);
            } else {
                newList.add(str.trim());
            }
        }
        return newList;
    }


    /**
     * 判断一个返回是否含有403
     * @param response
     * @return
     * @throws Exception
     */
    private  boolean isContains403(CloseableHttpResponse response) throws  Exception{
        boolean isContains403=false;
        String line;
        StringBuilder stringBuilder=new StringBuilder();
        InputStream inputStream=response.getEntity().getContent();
        InputStreamReader reader = new InputStreamReader(
                inputStream); // 建立一个输入流对象reader
        BufferedReader br = new BufferedReader(reader); // 建立一个对象，它把文件内容转成计算机能读懂的语言
        while ((line = br.readLine()) != null) {
            stringBuilder.append(line);
        }
        if(stringBuilder.toString().indexOf("升级维护(403)")>0){
            isContains403=true;
        }
        return  isContains403;
    }


    public  static void init(){
        try {
            //1.初始化比较数量
//            expectedTotal=Integer.valueOf(PropertiesClient.readValue(configFilePath+configfileName,expectedTotalKey));
//            expected403Total=Integer.valueOf(PropertiesClient.readValue(configFilePath+configfileName,expected403TotalKey));
            expectedTotal=Integer.valueOf(PropertiesClient.readValue(configfileName,expectedTotalKey));
            expected403Total=Integer.valueOf(PropertiesClient.readValue(configfileName,expected403TotalKey));
        } catch (NumberFormatException e) {
            throw new RuntimeException("配置文件中的数量必须为整数");
        }
    }



}
